package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.HttpUtils;
import com.ruoyi.system.service.IWechatLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 微信登录服务实现类
 * @author ChenYF
 * @date 2025-09-11 8:57
 */
@Service
public class WechatLoginServiceImpl implements IWechatLoginService {

    @Value("${wechat.appid}")
    private String appid;

    @Value("${wechat.secret}")
    private String secret;

    @Value("${wechat.redirect-uri}")
    private String redirectUri;

    // 微信开放平台授权URL
    private static final String WECHAT_AUTH_URL = "https://open.weixin.qq.com/connect/qrconnect";

    // 微信获取access_token的URL
    private static final String WECHAT_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";

    // 微信获取用户信息的URL
    private static final String WECHAT_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo";

    // Redis中存储state的前缀
    private static final String WECHAT_STATE_PREFIX = "wechat:state:";

    // Redis中存储用户信息的前缀
    private static final String WECHAT_USER_PREFIX = "wechat:user:";

    @Autowired
    private RedisService redisService;

    @Override
    public Map<String, String> generateQRCode(String state) {
        Map<String, String> result = new HashMap<>();

        // 构造微信扫码登录URL
        String qrCodeUrl = WECHAT_AUTH_URL +
                          "?appid=" + appid +
                          "&redirect_uri=" + redirectUri +
                          "&response_type=code" +
                          "&scope=snsapi_login snsapi_phone" +
                          "&state=" + state +
                          "#wechat_redirect";

        result.put("qrCodeUrl", qrCodeUrl);
        result.put("state", state);

        // 将state存入Redis，设置5分钟过期时间
        redisService.setCacheObject(WECHAT_STATE_PREFIX + state, "pending", 5l, TimeUnit.MINUTES);

        return result;
    }

    @Override
    public Map<String, Object> checkLoginStatus(String state) {
        Map<String, Object> result = new HashMap<>();

        // 检查state是否存在
        String status = redisService.getCacheObject(WECHAT_STATE_PREFIX + state);
        if (StringUtils.isEmpty(status)) {
            result.put("status", "expired"); // state已过期
            return result;
        }

        if ("pending".equals(status)) {
            result.put("status", "pending"); // 等待扫码
            return result;
        }

        if ("scanned".equals(status)) {
            result.put("status", "scanned"); // 已扫码，等待确认
            return result;
        }

        if ("confirmed".equals(status)) {
            // 已确认，获取用户信息
            String userInfoStr = redisService.getCacheObject(WECHAT_USER_PREFIX + state);
            if (StringUtils.isNotEmpty(userInfoStr)) {
                JSONObject userInfo = JSON.parseObject(userInfoStr);
                result.put("status", "confirmed");
                result.put("userInfo", userInfo);

                // 清除临时状态
                redisService.deleteObject(WECHAT_STATE_PREFIX + state);
                redisService.deleteObject(WECHAT_USER_PREFIX + state);
                return result;
            }
        }

        result.put("status", "failed");
        return result;
    }

    @Override
    public void processWechatCallback(String code, String state) {
        try {
            // 检查state是否存在
            String status = redisService.getCacheObject(WECHAT_STATE_PREFIX + state);
            if (StringUtils.isEmpty(status)) {
                return; // state已过期或无效
            }

            // 通过code获取access_token
            String tokenUrl = WECHAT_ACCESS_TOKEN_URL +
                             "?appid=" + appid +
                             "&secret=" + secret +
                             "&code=" + code +
                             "&grant_type=authorization_code";

            String tokenResponse = HttpUtils.sendGet(tokenUrl);
            JSONObject tokenJson = JSON.parseObject(tokenResponse);

            if (tokenJson.containsKey("errcode")) {
                // 获取access_token失败
                return;
            }

            String accessToken = tokenJson.getString("access_token");
            String openid = tokenJson.getString("openid");

            // 通过access_token和openid获取用户信息
            String userInfoUrl = WECHAT_USERINFO_URL +
                                "?access_token=" + accessToken +
                                "&openid=" + openid;

            String userInfoResponse = HttpUtils.sendGet(userInfoUrl);
            JSONObject userInfo = JSON.parseObject(userInfoResponse);

            // 更新状态为已确认
            redisService.setCacheObject(WECHAT_STATE_PREFIX + state, "confirmed", 5l, TimeUnit.MINUTES);
            redisService.setCacheObject(WECHAT_USER_PREFIX + state, userInfo.toJSONString(), 5l, TimeUnit.MINUTES);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
